package com.cennavi.minemap.controller;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.cennavi.minemap.bean.DataBean;
import com.cennavi.minemap.bean.LayerBean;
import com.cennavi.minemap.bean.LayerWithPrefixBean;
import com.cennavi.minemap.bean.MessageBean;
import com.cennavi.minemap.bean.SoluBean;
import com.cennavi.minemap.bean.SoluWithPrefixLayerBean;
import com.cennavi.minemap.bean.ThumbnailBean;
import com.cennavi.minemap.bean.UploadSoluBean;
import com.cennavi.minemap.service.LayerService;
import com.cennavi.minemap.service.SoluService;
import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
@ComponentScan(basePackages = { "com.cennavi.minemap.service" })
@RequestMapping("/service/solu")
public class SoluController {

	ObjectMapper objectMapper = new ObjectMapper();

	@Autowired
	private SoluService soluService;

	@Autowired
	private LayerService layerService;

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public @ResponseBody MessageBean insert(@RequestBody String json) throws Exception {
		SoluBean soluBean = objectMapper.readValue(json, SoluBean.class);
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.insert(soluBean);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu insert error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/update", method = RequestMethod.POST)
	public @ResponseBody MessageBean update(@RequestBody String json) throws Exception {
		SoluBean soluBean = objectMapper.readValue(json, SoluBean.class);
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.update(soluBean);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu update error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/delete/{id}")
	public @ResponseBody MessageBean delete(@PathVariable int id) {
		MessageBean messageBean = new MessageBean();
		int status = soluService.delete(id);
		if (status < 0) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu delete error");
		} else {
			messageBean.setErrcode(0);
		}
		return messageBean;
	}

	@RequestMapping(value = "/list/{userId}")
	public @ResponseBody MessageBean queryByUserId(@PathVariable int userId) {
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.queryByUserId(userId);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu list query error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/nameList/{userId}")
	public @ResponseBody MessageBean queryIdNameByUserId(@PathVariable int userId) {
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.queryIdNameByUserId(userId);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu list query error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/template/list")
	public @ResponseBody MessageBean queryTemplate() {
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.queryTemplate();
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu template list query error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/template2/list")
	public @ResponseBody MessageBean queryTemplate2ByUserId() {
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.queryTemplate2();
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu template2 list query error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/edit/{id}")
	public @ResponseBody MessageBean queryById(@PathVariable int id, @RequestParam("token") String token) {
		MessageBean messageBean = new MessageBean();

		if (soluService.queryTokenSolu(token, id) == 0) {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(1);
			List<SoluBean> list = new ArrayList<SoluBean>();
			SoluBean soluBean = new SoluBean();
			soluBean.setId(0);
			list.add(soluBean);
			dataBean.setRows(list);
			messageBean.setData(dataBean);

			return messageBean;
		}

		List<SoluBean> list = soluService.queryById(id);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu query error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/{id}")
	public @ResponseBody MessageBean queryPublishById(@PathVariable int id, @RequestParam("token") String token) {
		MessageBean messageBean = new MessageBean();

		if (soluService.queryTokenSolu(token, id) == 0) {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(1);
			List<SoluBean> list = new ArrayList<SoluBean>();
			SoluBean soluBean = new SoluBean();
			soluBean.setId(0);
			list.add(soluBean);
			dataBean.setRows(list);
			messageBean.setData(dataBean);

			return messageBean;
		}

		List<SoluBean> list = soluService.queryPublishById(id);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu query error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/url/{url}")
	public @ResponseBody MessageBean queryByUrl(@PathVariable String url, @RequestParam("token") String token) {
		MessageBean messageBean = new MessageBean();

		List<SoluBean> list = soluService.queryByUrl(url);

		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu query error");
		} else {

			int id = list.get(0).getId();

			if (soluService.queryTokenSolu(token, id) == 0) {
				DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
				messageBean.setErrcode(0);
				dataBean.setTotal(1);
				List<SoluBean> nulllist = new ArrayList<SoluBean>();
				SoluBean soluBean = new SoluBean();
				soluBean.setId(0);
				list.add(soluBean);
				dataBean.setRows(nulllist);
				messageBean.setData(dataBean);
				return messageBean;
			}
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/publish/{id}")
	public @ResponseBody MessageBean publish(@PathVariable int id) {
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.publish(id);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu publish error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/copy/{id}", method = RequestMethod.POST)
	public @ResponseBody MessageBean copy(@PathVariable int id, @RequestBody String json) throws Exception {
		SoluBean soluBean = objectMapper.readValue(json, SoluBean.class);
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.copy(id, soluBean);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu copy error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/style/edit/id/{id}")
	public @ResponseBody String queryStyle(@PathVariable int id, HttpServletRequest request) throws Exception {
		// soluService.queryById(id, getIpAddr(request));
		soluService.saveSoluLog(id, getIpAddr(request));
		String json = soluService.queryStyle(id).toJSONString();
		return json;
	}

	@RequestMapping(value = "/style/id/{id}")
	public @ResponseBody String queryPublishStyle(@PathVariable int id, HttpServletRequest request) throws Exception {
		// soluService.queryById(id, getIpAddr(request));
		soluService.saveSoluLog(id, getIpAddr(request));
		String json = soluService.queryPublishStyle(id).toJSONString();
		return json;
	}

	@RequestMapping(value = "/style/url/{url}")
	public @ResponseBody String queryStyle(@PathVariable String url, HttpServletRequest request) throws Exception {
		// List<SoluBean> list = soluService.queryByUrl(url, getIpAddr(request));
		List<SoluBean> list = soluService.saveSoluLogAndQuerySolu(url, getIpAddr(request));
		SoluBean soluBean = list.get(0);
		String json = soluService.queryPublishStyle(soluBean.getId()).toJSONString();
		return json;
	}

	@RequestMapping(value = "/export", method = RequestMethod.POST)
	public ResponseEntity<Resource> download(@RequestParam("id") Integer id, HttpServletResponse response)
			throws IOException {
		try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
			ObjectOutputStream objectOutputStream = new ObjectOutputStream(bos);
			objectOutputStream.writeObject(soluService.queryByIdForDownload(id));
			objectOutputStream.flush();
			objectOutputStream.close();
			HttpHeaders headers = new HttpHeaders();
			headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
			headers.add("Pragma", "no-cache");
			headers.add("Expires", "0");
			headers.add("charset", "utf-8");
			headers.add("Content-Disposition", "attachment;filename=\"" + id + "\"");
			Resource resource = new InputStreamResource(new ByteArrayInputStream(bos.toByteArray()));
			return ResponseEntity.ok().headers(headers)
					.contentType(MediaType.parseMediaType("application/x-msdownload")).body(resource);
		}
	}

	@Transactional
	@RequestMapping(value = "/import", method = RequestMethod.POST)
	public Integer upload(@RequestParam("file") MultipartFile file, @RequestParam("userId") Integer userId,
			HttpServletRequest request) throws IOException {
		ObjectInputStream ois = new ObjectInputStream(file.getInputStream());
		try {
			@SuppressWarnings("unchecked")
			Map<String, Object> map = (Map<String, Object>) ois.readObject();
			SoluBean soluBean = (SoluBean) map.get("solu");
			soluBean.setUserId(userId);
			@SuppressWarnings("unchecked")
			List<LayerWithPrefixBean> layerBeans = (List<LayerWithPrefixBean>) map.get("layers");
			List<SoluBean> list = soluService.insert(soluBean);
			Integer id = list.get(0).getId();

			for (LayerWithPrefixBean layerBean : layerBeans) {
				layerBean.setSoluId(id);
				layerService.insertUnReturn(layerBean);
			}
			return id;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			return 0;
		}
	}

	@RequestMapping(value = "/upload/findSolu/{uploadId}")
	public @ResponseBody MessageBean querySoluListByUploadId(@PathVariable Integer uploadId) {
		MessageBean messageBean = new MessageBean();
		List<SoluBean> list = soluService.querySoluListByUploadId(uploadId);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("find solu by uploadId list query error");
		} else {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/upload/update/", method = RequestMethod.POST)
	public @ResponseBody MessageBean updateUploadSolu(@RequestBody String json) throws Exception {
		UploadSoluBean uploadSoluBean = objectMapper.readValue(json, UploadSoluBean.class);
		MessageBean messageBean = new MessageBean();
		int status = soluService.updateUploadSolu(uploadSoluBean);
		if (status < 0) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("upload solu update error");
		} else {
			messageBean.setErrcode(0);
			messageBean.setErrmsg(null);
		}

		return messageBean;
	}
	
	@RequestMapping(value = "/thumbnail/add", method = RequestMethod.POST)
	public @ResponseBody MessageBean insertThumbnail(@RequestBody String json) throws Exception {
		ThumbnailBean thumbnailBean = objectMapper.readValue(json, ThumbnailBean.class);
		MessageBean messageBean = new MessageBean();
		List<ThumbnailBean> list = soluService.insertThumbnail(thumbnailBean);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("thumbnail insert error");
		} else {
			DataBean<ThumbnailBean> dataBean = new DataBean<ThumbnailBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}
	
	@RequestMapping(value = "/thumbnail/update", method = RequestMethod.POST)
	public @ResponseBody MessageBean updateThumbnail(@RequestBody String json) throws Exception {
		ThumbnailBean thumbnailBean = objectMapper.readValue(json, ThumbnailBean.class);
		MessageBean messageBean = new MessageBean();
		List<ThumbnailBean> list = soluService.updateThumbnail(thumbnailBean);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("thumbnail update error");
		} else {
			DataBean<ThumbnailBean> dataBean = new DataBean<ThumbnailBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	@RequestMapping(value = "/thumbnail/delete/{soluId}")
	public @ResponseBody MessageBean deleteThumbnail(@PathVariable int soluId) {
		MessageBean messageBean = new MessageBean();
		int status = soluService.deleteThumbnail(soluId);
		if (status < 0) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("thumbnail delete error");
		} else {
			messageBean.setErrcode(0);
		}
		return messageBean;
	}
	
	@RequestMapping(value = "/thumbnail/find/{soluId}")
	public @ResponseBody MessageBean queryThumbnailBySoluId(@PathVariable int soluId) {
		MessageBean messageBean = new MessageBean();
		List<ThumbnailBean> list = soluService.queryThumbnail(soluId);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("thumbnail query error");
		} else {
			DataBean<ThumbnailBean> dataBean = new DataBean<ThumbnailBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}

	public String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		if (ip == null || ip.length() == 0) {
			return ip.split(",")[0];
		} else {
			return "unknown";
		}

	}
	
	@RequestMapping(value = "/withPrefixLayer/{id}")
	public @ResponseBody MessageBean queryWithPrefixLayerById(@PathVariable int id, @RequestParam("token") String token) {
		MessageBean messageBean = new MessageBean();

		if (soluService.queryTokenSolu(token, id) == 0) {
			DataBean<SoluBean> dataBean = new DataBean<SoluBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(1);
			List<SoluBean> list = new ArrayList<SoluBean>();
			SoluBean soluBean = new SoluBean();
			soluBean.setId(0);
			list.add(soluBean);
			dataBean.setRows(list);
			messageBean.setData(dataBean);

			return messageBean;
		}

		List<SoluWithPrefixLayerBean> list = soluService.queryWithPrefixLayerById(id);
		if (list == null) {
			messageBean.setErrcode(-1);
			messageBean.setErrmsg("solu query error");
		} else {
			DataBean<SoluWithPrefixLayerBean> dataBean = new DataBean<SoluWithPrefixLayerBean>();
			messageBean.setErrcode(0);
			dataBean.setTotal(list.size());
			dataBean.setRows(list);
			messageBean.setData(dataBean);
		}
		return messageBean;
	}
	
	private final Logger logger = Logger.getLogger(getClass());
	@Autowired
	private DiscoveryClient client;
	@RequestMapping(value = "/test")
	public @ResponseBody MessageBean test() {
		ServiceInstance instance = client.getLocalServiceInstance();
		logger.info("host:" + instance.getHost() + ", service_id:" + instance.getServiceId());
		MessageBean msg = new MessageBean();
		msg.setErrcode(99);
		msg.setErrmsg("测试");
		return msg;
	}
	
	
	
}
